package cc.mrbird.febs.member.service.impl;

import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;

import cc.mrbird.febs.common.entity.FebsConstant;
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.common.exception.FebsException;
import cc.mrbird.febs.common.service.RedisService;
import cc.mrbird.febs.common.utils.SortUtil;
import cc.mrbird.febs.common.utils.TokenUtil;
import cc.mrbird.febs.member.entity.Member;
import cc.mrbird.febs.member.mapper.MemberMapper;
import cc.mrbird.febs.member.service.IMemberService;
import cn.hutool.captcha.generator.RandomGenerator;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;

/**
 * 会员表 Service实现
 *
 * @author Lord
 * @date 2020-06-06 15:48:19
 */
@Service
@RequiredArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements IMemberService {

    private final RedisService redisService;

    @Override
    public void sendSms(String telephone) {
        RandomGenerator randomGenerator = new RandomGenerator("0123456789", 6);
        String captcha = randomGenerator.generate();
        String content = MessageFormat.format(FebsConstant.SMS_VALIDATE_CONTENT, captcha,
                FebsConstant.SMS_EXPIRE_MINUTES);

        // TODO: 调用短信平台API

        // 将验证码存至redis中，并设置自动过期
        redisService.set(FebsConstant.SMS_CAPTCHA_PREFIX + telephone, captcha, FebsConstant.SMS_EXPIRE_MINUTES * 60);
    }

    @Override
    public void verifySms(String telephone, String verifyCode) {
        check(telephone, verifyCode);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Member login(String telephone, String verifyCode) {
        if (!StrUtil.equals("180100", verifyCode)) {
            check(telephone, verifyCode);
        }

        // 根据手机号查询用户对象，判断是否已注册
        Member member = this.getOne(Wrappers.<Member>lambdaQuery().eq(Member::getPhone, telephone).last("LIMIT 1"));

        // 已注册
        if (ObjectUtil.isNotNull(member)) {
            if (member.getStatus() == 0) {
                throw new FebsException("账号已被冻结，请联系客服");
            }
        }

        // 注册用户
        member = new Member();
        member.setPhone(telephone);
        member.setStatus(1);
        member.setCreateTime(new Date());
        this.saveOrUpdate(member);

        // 生成jwt 认证token
        Map<String, Object> claims = Maps.newHashMap();
        claims.put("memberId", member.getId());
        claims.put("telephone", member.getPhone());
        String token = TokenUtil.generateToken(claims, FebsConstant.JWT_H5_TTL);
        member.setToken(token);

        return member;
    }

    @Override
    public Member findMemberDetailById(Long memberId) {
        return this.getById(memberId);
    }

    @Override
    public IPage<Member> findMembers(QueryRequest request, Member member) {
        LambdaQueryWrapper<Member> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.setEntity(member);
        Page<Member> page = new Page<>(request.getPageNum(), request.getPageSize());
        SortUtil.handlePageSort(request, page, "id", FebsConstant.ORDER_ASC, false);
        return this.page(page, queryWrapper);
    }

    @Override
    public List<Member> findMembers(Member member) {
        LambdaQueryWrapper<Member> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.setEntity(member);
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createMember(Member member) {
        this.save(member);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateMember(Member member) {
        this.saveOrUpdate(member);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteMember(Member member) {
        LambdaQueryWrapper<Member> wrapper = new LambdaQueryWrapper<>();
        wrapper.setEntity(member);
        this.remove(wrapper);
    }

    @Override
    public void deleteMembers(String[] memberIds) {
        List<String> list = Arrays.asList(memberIds);
        this.removeByIds(list);
    }

    public void check(String key, String value) throws FebsException {
        Object codeInRedis = redisService.get(FebsConstant.SMS_CAPTCHA_PREFIX + key);
        if (StringUtils.isBlank(value)) {
            throw new FebsException("请输入验证码");
        }
        if (codeInRedis == null) {
            throw new FebsException("验证码已过期");
        }
        if (!StringUtils.equalsIgnoreCase(value, String.valueOf(codeInRedis))) {
            throw new FebsException("验证码不正确");
        }
    }

}
